#include"jpg.h"
int k=0;
void read_all_data(int fd, char *buf, int total_size)
{
	int n, m=0;
	while(total_size > 0)
	{
		n = read(fd, buf+m, total_size);
		if(n == -1)
		{
			perror("读取文件数据失败");
			exit(0);
		}

		if(n == 0)
			break;

		total_size -= n;
		m += n;
	}
}

char *load_file(char *jpgfile, struct image_info *minfo)
{
	// 获取文件的大小
	struct stat finfo;
	bzero(&finfo, sizeof(finfo));
	stat(jpgfile, &finfo);

	// 根据大小申请内存来存放 JPG 数据
	char *jpgdata = calloc(1, finfo.st_size);
	if(jpgdata == NULL)
	{
		perror("申请内存失败");
		exit(0);
	}

	// 将数据全部读到 jpgdata 中
	int fd = open(jpgfile, O_RDONLY);
	read_all_data(fd, jpgdata, finfo.st_size);


	/*********** 调用 JPG 库的固定套路 ***************/

	// 声明解压缩结构体，以及错误管理结构体
	struct jpeg_decompress_struct cinfo;
	struct jpeg_error_mgr jerr;

	// 使用缺省的出错处理来初始化解压缩结构体
	cinfo.err = jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	// 配置该cinfo，使其从jpgdata中读取jpg_size个字节
	// 这些数据必须是完整的JPEG数据
	jpeg_mem_src(&cinfo, jpgdata, finfo.st_size);


	// 读取JPEG文件的头，并判断其格式是否合法
	int ret = jpeg_read_header(&cinfo, true);
	if(ret != 1)
	{
		fprintf(stderr, "[%d]: jpeg_read_header failed: "
			"%s\n", __LINE__, strerror(errno));
		exit(0);
	}

	// 开始解压
	jpeg_start_decompress(&cinfo);

	minfo->width = cinfo.output_width;
	minfo->height = cinfo.output_height;
	minfo->pixel_size = cinfo.output_components;

	int row_stride = minfo->width * minfo->pixel_size;

	// 根据图片的尺寸大小，分配一块相应的内存rgbdata
	// 用来存放从jpgdata解压出来的图像数据
	unsigned long rgb_size;
	unsigned char *rgbdata;
	rgb_size = minfo->width *
			minfo->height * minfo->pixel_size;
	rgbdata = (unsigned char *)calloc(1, rgb_size);

	// 循环地将图片的每一行读出并解压到rgbdata中
	int line = 0;
	while(cinfo.output_scanline < cinfo.output_height)
	{
		unsigned char *buffer_array[1];
		buffer_array[0] = rgbdata +
				(cinfo.output_scanline) * row_stride;
		jpeg_read_scanlines(&cinfo, buffer_array, 1);
	}

	// 解压完了，将jpeg相关的资源释放掉
 	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	free(jpgdata);

	

	return rgbdata;
}
void display(char *rgbdata,struct image_info *minfo,
		int lcd,int xoffset, int yoffset)
{
	struct fb_var_screeninfo vinfo;
	bzero(&vinfo,sizeof(vinfo));
	ioctl(lcd,FBIOGET_VSCREENINFO, &vinfo);
	int screensize=vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;
	char *fbmem=mmap(NULL,screensize*2,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
	
	//vinfo.xoffset=0;
	//vinfo.yoffset=0;
	//ioctl(lcd, FBIOPAN_DISPLAY, &vinfo);
	
	
	
	int lcd_w = vinfo.xres - xoffset;
	int lcd_h = vinfo.yres - yoffset;


	int rgb_offset = 0;
	int lcd_offset = 0;

	int i,j;
	//将像素点逐行写入LCD屏幕	
	int n=800*480*4*((k+1)%2);
	//bzero(fbmem,vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8);
	fbmem+=n;
	//图片宽高度均等于LCD宽高度
	if(minfo->height==vinfo.yres&&minfo->width==vinfo.xres)
	{
	fbmem += (yoffset * vinfo.xres + xoffset) * vinfo.bits_per_pixel/8;
	bzero(fbmem,vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8);
	for(j=0; j<lcd_h && j<minfo->height; j++)
	{
		for(i=0; i<lcd_w && i<minfo->width; i++)
		{
			rgb_offset = minfo->pixel_size*i + minfo->width*minfo->pixel_size*j;
			lcd_offset = (vinfo.bits_per_pixel/8)*i + (vinfo.xres*vinfo.bits_per_pixel/8)*j;

			memcpy(fbmem+vinfo.red.offset/8+lcd_offset,  rgbdata+rgb_offset+0,  1);
			memcpy(fbmem+vinfo.green.offset/8+lcd_offset,rgbdata+rgb_offset+1,1);
			memcpy(fbmem+vinfo.blue.offset/8+lcd_offset, rgbdata+rgb_offset+2, 1);
		}
	}
	}
	//图片宽高度均小于LCD屏幕的宽高
	else if(vinfo.xres>minfo->width&&vinfo.yres>minfo->height)
	{
		//printf("11.finish\n");
		bzero(fbmem,vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8);
		int xcenter=(vinfo.xres - minfo->width)/2;
		int ycenter=(vinfo.yres - minfo->height)/2;
		fbmem+=(ycenter*vinfo.xres+xcenter)*vinfo.bits_per_pixel/8;
		lcd_w=vinfo.xres-xcenter;
		lcd_h=vinfo.yres-ycenter;

		for(j=0;j<lcd_h&&j<minfo->height;j++){
			for(i=0;i<lcd_w&&i<minfo->width;i++){
			 lcd_offset=(vinfo.xres*j+i)*4;
			 rgb_offset=(minfo->width*j+i)*minfo->pixel_size;
	
			memcpy(fbmem+lcd_offset+vinfo.red.offset/8,rgbdata+rgb_offset+0,1);
			memcpy(fbmem+lcd_offset+vinfo.green.offset/8,rgbdata+rgb_offset+1,1);
			memcpy(fbmem+lcd_offset+vinfo.blue.offset/8,rgbdata+rgb_offset+2,1);
			}}
	}
	//图片填充
	else
	{
		//printf("12.finish\n");
		//bzero(fbmem, vinfo.xres * vinfo.yres * 4);
		//bzero(fbmem,vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8);
		float hplus=(float)(minfo->height - vinfo.yres)/(float)vinfo.yres;
		float wplus=(float)(minfo->width - vinfo.xres)/(float)vinfo.xres;
		//printf("h%f,w%f\n",hplus,wplus);

		for(j=0; j<vinfo.yres && j<minfo->height; j++)
		{
		for(i=0; i<vinfo.xres&& i<minfo->width; i++)
		{
			rgb_offset = minfo->pixel_size*(i+(int)(i*wplus))+ minfo->width*minfo->pixel_size*(j+(int)(j*hplus));
			lcd_offset = (vinfo.bits_per_pixel/8)*i
					+ (vinfo.xres*vinfo.bits_per_pixel/8)*j;

			memcpy(fbmem+vinfo.red.offset/8+lcd_offset,  rgbdata+rgb_offset+0,  1);
			memcpy(fbmem+vinfo.green.offset/8+lcd_offset,rgbdata+rgb_offset+1,1);
			memcpy(fbmem+vinfo.blue.offset/8+lcd_offset, rgbdata+rgb_offset+2, 1);
		}
	}
	}
	
	
	k++;
	
	vinfo.xoffset=0;
	vinfo.yoffset=(k%2)*480;
	ioctl(lcd, FBIOPAN_DISPLAY, &vinfo);


}
